package com.mp.approvalreq.service.impl;

import com.mp.approvalreq.dao.GeneralRequestDao;
import com.mp.approvalreq.dao.impl.GeneralRequestDaoImpl;
import com.mp.approvalreq.entity.ConditionFlow;
import com.mp.approvalreq.entity.DuplicateStrategy;
import com.mp.approvalreq.entity.Flow;
import com.mp.approvalreq.entity.GeneralRequest.GeneralRequest;
import com.mp.approvalreq.entity.RequestFlowType;
import com.mp.approvalreq.service.strategy.DuplicateStrategyImpl;
import com.mp.approvalreq.service.GeneralRequestServiceServant;
import com.mp.approvalreq.service.strategy.FlowFactory;
import com.mp.approvalreq.util.DbName;
import com.mp.approvalreq.util.ErrorUtils;
import com.mp.approvalreq.util.FlowUtils;
import com.mp.approvalreq.util.ListHelper;
import com.mp.auth.entity.CommonSetting;
import com.mp.auth.service.CommonSettingServicePrx;
import com.mp.user.entity.User;
import com.mp.user.service.UserServicePrx;
import com.plusmoney.exception.RpcServerLogicalException;
import com.plusmoney.jdbc.util.DBUtils;
import com.plusmoney.util.Utils;
import com.qq.tars.client.util.ServantUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class GeneralRequestServiceServantImpl implements GeneralRequestServiceServant {

    private static final Logger logger = LoggerFactory.getLogger(GeneralRequestServiceServantImpl.class);

    @Override
    public void handQuitUser(User user) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            GeneralRequestDao generalRequestDao = new GeneralRequestDaoImpl(connection);

            List<GeneralRequest> generalRequestList = filterNeedModifyRequestFlows(user, generalRequestDao);

            List<GeneralRequest> conditionFlows = filterNeedModifyConditionFlows(user, generalRequestDao);

            DBUtils.begin(connection);
            if (Utils.isNotEmpty(generalRequestList)) {
                generalRequestDao.updateBatchGeneralRequestFlow(generalRequestList);
            }
            if (Utils.isNotEmpty(conditionFlows)) {
                generalRequestDao.updateBatchGeneralConditionFlow(conditionFlows);
            }
            DBUtils.commit(connection);
        } catch (Throwable throwable) {
            DBUtils.rollback(connection);
            logger.error(throwable.getMessage(), throwable);
            throw ErrorUtils.throwError(throwable);
        } finally {
            DBUtils.release(connection);
        }
    }

    @Override
    public GeneralRequest calculateRequestFlow(GeneralRequest dto) throws Throwable {
        Connection connection = DBUtils.getConnection(DbName.APPROVALREQ);
        try {
            UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
            GeneralRequestDao generalRequestDao = new GeneralRequestDaoImpl(connection);

            User user = userServicePrx.getUserByContactId(dto.getApplicant());

            GeneralRequest generalRequest = generalRequestDao.selectProjectGeneralRequest(dto.getCompanyId(), dto.getProject(), dto.getSpecificId());
            if (Utils.isNull(generalRequest)) {
                generalRequest = generalRequestDao.selectProjectDefaultGeneralRequest(dto.getCompanyId(), dto.getProject());
            }

            String templateFlow = getTemplateFlow(generalRequest);

            if (RequestFlowType.CONDITION.equals(templateFlow)) {
                List<ConditionFlow> conditionFlows = generalRequestDao.selectConditionFlowsById(generalRequest.getGeneralFlowId(), dto.getCompanyId());
                templateFlow = findRequestFlowFromCondition(dto, conditionFlows);
            }
            if (RequestFlowType.ALTERNATIVE.equals(templateFlow)) {
                if (StringUtils.isEmpty(dto.getRequestFlow())) {
                    throw new RpcServerLogicalException(1, "请选择第一层审批人");
                }
            }

            List<Flow> flows = FlowFactory.build(user, templateFlow, dto.getRequestFlow());

            try {
                CommonSettingServicePrx commonSettingServicePrx = ServantUtils.getObject(CommonSettingServicePrx.class);
                CommonSetting commonSetting = commonSettingServicePrx.getCommonSetting(user.getCompanyId(), "erp", "checkApproverDuplicate");
                DuplicateStrategy duplicateStrategy = new DuplicateStrategyImpl(Integer.parseInt(commonSetting.getContent()));
                flows = duplicateStrategy.removeRepeat(flows);
            } catch (Throwable throwable) {
                logger.error(throwable.getMessage(), throwable);
            }

            dto.setAllJudger(FlowUtils.getContactIds(flows));
            dto.setRequestFlow(templateFlow);
            return dto;
        } catch (Throwable throwable) {
            DBUtils.rollback(connection);
            logger.error(throwable.getMessage(), throwable);
            throw ErrorUtils.throwError(throwable);
        } finally {
            DBUtils.release(connection);
        }
    }

    private String findRequestFlowFromCondition(GeneralRequest dto, List<ConditionFlow> conditionFlows) {
        ConditionFlow condition = Utils.getFirst(conditionFlows);
        // 订单审批流 - 订单类型
        int conditionType = 0;
        try {
            conditionType = Integer.parseInt(condition.getConditionType());
        } catch (NumberFormatException e) {
            logger.error(e.getMessage(), e);
        }
        if (dto.getProject() == 1 && conditionType >= 3) {
            for (ConditionFlow conditionFlow : conditionFlows) {
                if (ListHelper.findElement(ListHelper.string2StringList(conditionFlow.getRange()), dto.getItem())) {
                    return conditionFlow.getRequestFlow();
                }
            }
        } else {
            return chooseConditionRequestFlowForCRMOrder(dto, conditionFlows);
        }

        return RequestFlowType.DEFAULT;
    }

    private String chooseConditionRequestFlowForCRMOrder(GeneralRequest dto, List<ConditionFlow> conditionFlows) {
        BigDecimal amount = dto.getAmount();
        if (amount == null) {
            throw new RpcServerLogicalException(1, "金额数目为空");
        }
        logger.info("amount:" + amount);
        for (int i = 0; i < conditionFlows.size(); i++) {
            ConditionFlow cf = conditionFlows.get(i);
            BigDecimal min = cf.getSmallerFactor();
            BigDecimal max = cf.getGreaterFactor();
            logger.info("min:" + min);
            logger.info("max:" + min);

            // 金额的比较，这个是单项的，所以找到num进行比较
            if (max != null) {
                //min < val <= max
                if (min.compareTo(amount) < 0 && max.compareTo(amount) > -1) {
                    return cf.getRequestFlow();
                } else {
                    // 如果是第一个条件，而且最小值和发送条件是一样的，则满足
                    if (i == 0 && min.equals(amount)) {
                        return cf.getRequestFlow();
                    }
                }
            } else {
                //min < val
                if (min.compareTo(amount) < 0) {
                    return cf.getRequestFlow();
                }
            }
        }
        throw new RpcServerLogicalException(1, "无满足的审批条件导致无法确认审批流");
    }

    private String getTemplateFlow(GeneralRequest generalRequest) {
        if (Utils.isNull(generalRequest)) {
            return RequestFlowType.DEFAULT;
        }
        if (StringUtils.isEmpty(generalRequest.getAllJudger())) {
            return RequestFlowType.DEFAULT;
        }
        return generalRequest.getAllJudger();
    }

    private List<GeneralRequest> filterNeedModifyConditionFlows(User user, GeneralRequestDao generalRequestDao) throws Throwable {
        List<GeneralRequest> list = new ArrayList<>();
        List<GeneralRequest> conditionFlowList = generalRequestDao.selectAllGeneralConditionFlowByCompanyId(user.getCompanyId());
        if (Utils.isEmpty(conditionFlowList)) {
            logger.info("该公司不存在通用条件审批流");
            return list;
        }

        UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
        User admin = userServicePrx.getAdminUser(user.getCompanyId());

        for (GeneralRequest generalRequest : conditionFlowList) {
            List<String> flows = new ArrayList<>(Arrays.asList(generalRequest.getAllJudger().split(",")));
            boolean isModify = false;
            for (int i = 0; i < flows.size(); i++) {
                String judger = flows.get(i);
                if (!String.valueOf(user.getContactId()).equals(judger)) {
                    continue;
                }
                isModify = true;
                flows.remove(i);
                i--;
                if (i == flows.size() - 1) {
                    flows.add(String.valueOf(admin.getContactId()));
                }
            }
            if (isModify) {
                generalRequest.setAllJudger(Utils.list2string(flows).replaceAll(" ", ""));
                list.add(generalRequest);
            }
        }
        return list;
    }

    /**
     * 过滤需要重置的审批流
     *
     * @param user
     * @param generalRequestDao
     * @return
     * @throws Throwable
     */
    private List<GeneralRequest> filterNeedModifyRequestFlows(User user, GeneralRequestDao generalRequestDao) throws Throwable {
        List<GeneralRequest> list = new ArrayList<>();
        List<GeneralRequest> generalRequestList = generalRequestDao.selectAllGeneralRequestFlowByCompanyId(user.getCompanyId());

        if (Utils.isEmpty(generalRequestList)) {
            logger.info("公司不存在通用审批流");
            return list;
        }
        UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
        User admin = userServicePrx.getAdminUser(user.getCompanyId());

        for (GeneralRequest generalRequest : generalRequestList) {
            List<String> allJudgers = new ArrayList<>(Arrays.asList(generalRequest.getAllJudger().split(",")));
            boolean isModify = false;
            for (int i = 0; i < allJudgers.size(); i++) {
                String judger = allJudgers.get(i);
                if (!String.valueOf(user.getContactId()).equals(judger)) {
                    continue;
                }
                isModify = true;
                allJudgers.remove(i);
                i--;
                if (i == allJudgers.size() - 1) {
                    allJudgers.add(String.valueOf(admin.getContactId()));
                }
            }
            if (isModify) {
                generalRequest.setAllJudger(Utils.list2string(allJudgers).replaceAll(" ", ""));
                list.add(generalRequest);
            }
        }
        return list;
    }
}
